<?php
class Pageley_Controller_Form extends Pageley_Controller_Basic {
	protected $commandClassName;

	public function __construct($views, $commandClassName) {
		parent::__construct($views);
		$this->commandClassName = $commandClassName;
	}

    public function handleRequest($parameters) {
        if(Pageley_Log::isTraceEnabled($this)) {
			Pageley_Log::trace($this, "Creating and populating command of class '" . $this->commandClassName . "'.");
		}
		$command = $this->createCommand();
		$this->populateCommand($command, $parameters);
        if(Pageley_Log::isTraceEnabled($this)) {
			Pageley_Log::trace($this, "Executing command of class '" . $this->commandClassName . "'.");
		}
        $modelAndView = $this->executeCommand($command);
        return $modelAndView;
    }
    
	protected function createCommand() {
		return Pageley_Util_Reflection::newInstance($this->commandClassName, null);
	}

	protected function populateCommand($command, $parameters) {
		$class = new ReflectionClass($this->commandClassName);
		foreach($class->getMethods() as $index => $method) {
			$methodName = $method->getName();
			if(Pageley_Util_String::startsWith($methodName, "set") &&
			         Pageley_Util_String::length($methodName) > 3 && $method->isPublic()) {
				$propertyName = Pageley_Util_String::uncapitalize(Pageley_Util_String::substring($methodName, 3));
				$value = null;
				if($parameters->containsKey($propertyName)) {
				    $value = $parameters->get($propertyName);
				} else {
				    $i = 0;
                    do {
                    	$v = null;
                    	if($parameters->containsKey($propertyName . $i)) {
                            $v = $parameters->get($propertyName . $i);
                            if($value === null) {
                            	$value = new Pageley_Util_ArrayMap();
                            }
                            $value->add($v);
                            $i++;
                        }
                    } while($v != null);
                } 
                if(is_array($value)) {
                    $value = new Pageley_Util_ArrayMap($value);
                }
				$method->invoke($command, $value);
			}
		}
	}

    protected function executeCommand($command) {
        $modelAndView = null;
        try {
			$modelAndView = $command->execute();
			if($modelAndView === null) {
				$modelAndView = new Pageley_Controller_ModelAndView();
			}
			$modelAndView->setView($this->getView(Pageley_Controller_Result::SUCCESS));
			if(Pageley_Log::isTraceEnabled($this)) {
				Pageley_Log::trace($this, "Command '" . $command . "' successful.");
			}
		} catch(Pageley_Controller_Exception $exception) {
            $model = $exception->getModel();
            if($model === null) {
                $model = new Pageley_Util_ArrayMap();
            }
		    if($exception->getCause() !== null) {
        		$errors = $exception->getCause()->getErrors();
                Pageley_Log::warn($this, "Command '" . $command . "' failed: " . $errors);
                $model->put("errors", $errors);
		    }
			$modelAndView = new Pageley_Controller_ModelAndView($model, $this->getView(Pageley_Controller_Result::FAILURE));
		    $modelAndView->setAfterViewAction($exception->getAfterViewAction());
		}
        return $modelAndView;
    }
}